package com.superhelper.app.controller;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.superhelper.app.common.CommonHelper;
import com.superhelper.app.common.Consts;
import com.superhelper.app.controller.base.AbstractController;
import com.superhelper.app.domain.Admin;
import com.superhelper.app.domain.InvitationCode;
import com.superhelper.app.domain.Resp;
import com.superhelper.app.domain.RespShop;
import com.superhelper.app.service.DeliverService;
import com.superhelper.app.service.OrderService;
import com.superhelper.common.domain.DeliverAccount;
import com.superhelper.common.domain.ExtMsg;
import com.superhelper.common.domain.LoginLog;
import com.superhelper.common.domain.TakeOutShopInfo;
import com.superhelper.common.service.PushService;

/**
 * 
 * */
@Controller
@RequestMapping("v1/user")
public class UserController extends AbstractController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private DeliverService deliverService;
    @Autowired
    protected PushService pushService;

    /**
     * 登录校验
     * 
     * @param username
     *            用户名(必传)
     * @param pwd
     *            　　　　 密码　(必传)
     * @return map 校验结果
     */
    @ResponseBody
    @RequestMapping("login.do")
    public Resp login(@RequestParam String phone, @RequestParam String pwd, HttpServletRequest request) {

        Admin user = adminService.getAdminByUsername(phone);
        if (user == null) {
            return resp(Consts.Code.USER_NOT_EXISTS);
        }
        if (!user.getPwd().equals(pwd)) {
            return resp(Consts.Code.DATA_ERROR, "账号或密码错误");
        }
        this.addLogin(user, request);
        String token = generateToken(user.getId(), user.getImid());
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", user.getId());
        map.put("imid", user.getImid());
        map.put("token", token);
        if (user.getInvitCode() != null) {
            map.put("invitCode", user.getInvitCode().getCode());
            map.put("expireAt", user.getExpireAt());
            long day = Consts.DAY_AGE * 1000;
            long time = CommonHelper.getDateFormat("yyyy-MM-dd", new Date()).getTime();
            long expireAt = CommonHelper.getDateFormat("yyyy-MM-dd", user.getExpireAt()).getTime();
            long expireDay = (expireAt - time) / day;
            if (expireDay < 0) {
                expireDay = 0;
            }
            map.put("expireDay", expireDay);
        }
        return success(map);
    }

    /**
     * 登录日志
     * 
     * @param ll
     */
    private void addLogin(final Admin user, final HttpServletRequest request) {
        final String userAgent = request.getHeader("user-agent");
        final String version = request.getHeader("gzVersion");
        final String ip = request.getRemoteAddr();
        final String model = request.getHeader("model");
        final String device = request.getHeader("device");
        final String deviceAgent = request.getHeader("Device-Agent");
        final String plfFrom = request.getHeader("plfFrom");
        final String packageName = request.getHeader("packageName");
        final LoginLog ll = new LoginLog();
        ll.setUserId(user.getId());
        ll.setDevice(device);
        ll.setUserAgent(userAgent);
        ll.setIp(ip);
        ll.setVersion(version);
        ll.setModel(model);
        ll.setLoginTime(new Date());
        ll.setDeviceAgent(deviceAgent);
        ll.setImid(user.getImid());
        ll.setPlfFrom(plfFrom);
        ll.setPackageName(packageName);

        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (device.contains("pcweb")) {// pc端登录
                    CommonHelper.setSessionUser(user, request);
                    ll.setDeviceAgent("pcweb_" + user.getImid());
                    adminService.setUserOnline(user.getId());
                } else {
                    Map<String, Object> msgMap = new HashMap<>();
                    msgMap.put("userId", user.getId());
                    msgMap.put("type", "on_line");
                    msgMap.put("uuid", deviceAgent);
                    msgMap.put("retry", false);
                    ExtMsg extras = new ExtMsg("user", msgMap);
                    String title = "用户登录消息";
                    pushService.sendToUser(title, title, user.getImid(), extras);
                    adminService.updatePackageName(packageName, plfFrom, user.getId());
                }
                String loginKey = Consts.Cache.USER_LOGIN_PREFIX + user.getId();
                LoginLog entity = redisService.get(loginKey, LoginLog.class);
                if (entity == null) {
                    orderService.updatePrintProcess(user.getId());// 如果是不用平台登录，则将登录前的订单设置成已打印
                } else if (!entity.getDeviceAgent().equals(ll.getDeviceAgent())) {
                    orderService.updatePrintProcess(user.getId());// 如果是不用平台登录，则将登录前的订单设置成已打印
                }
                adminService.addLoginLog(ll);
                redisService.set(loginKey, ll);// 记录最后登录的信息
            }
        });

    }

    /**
     * 新版用户注册接口
     * 
     * @param phone
     *            手机号
     * @Param verifyCode 验证码
     * @param pwd
     *            MD5密码
     */
    @RequestMapping("/register")
    @ResponseBody
    public Resp register(@RequestParam String phone, @RequestParam String verifyCode, @RequestParam String pwd,
            HttpServletRequest request) {

        Admin user = adminService.getAdminByUsername(phone);
        if (user != null) { // 手机号码被注册
            return resp(Consts.Code.USER_PHONE_EXISTS, "手机已被注册");
        }
        if (!verifyCode("register", verifyCode, phone)) { // 验证码错误
            return resp(Consts.Code.VERIFY_CODE_INVALID, "验证码错误");
        }
        user = new Admin();
        user.setPwd(pwd);
        user.setUsername(phone);
        int res = adminService.createUser(user);
        Map<String, Object> result = new HashMap<>();
        if (res > 0) {
            Admin entity = adminService.getAdminById(user.getId());
            result.put("imid", entity.getImid());
            result.put("id", entity.getId());
            result.put("token", generateToken(entity.getId(), entity.getImid()));
            if (user.getInvitCode() != null) {
                result.put("invitCode", user.getInvitCode().getCode());
                result.put("expireAt", user.getExpireAt());
                long day = Consts.DAY_AGE * 1000;
                long time = CommonHelper.getDateFormat("yyyy-MM-dd", new Date()).getTime();
                long expireAt = CommonHelper.getDateFormat("yyyy-MM-dd", user.getExpireAt()).getTime();
                long expireDay = (expireAt - time) / day;
                if (expireDay < 0) {
                    expireDay = 0;
                }
                result.put("expireDay", expireDay);
            }
            this.addLogin(user, request);
            if (online) {
                String adminPhone = "15521006673";
                String tpl_id = "32439";
                String tpl_value = "#content#=" + phone;
                // smsHandler.send(adminPhone, tpl_id, tpl_value);//
            }
        }
        return res > 0 ? success(result) : fail();

    }

    /**
     * 　忘记密码　
     * 
     * @param pwd
     *            用户密码
     * @param newpwd
     *            新密码
     * @param userId
     *            用户ID
     * @return
     */
    @ResponseBody
    @RequestMapping("/forgetPwd")
    public Resp forgetPwd(@RequestParam String phone, @RequestParam String pwd, @RequestParam String verifyCode) {

        if (!verifyCode("forgetPwd", verifyCode, phone)) { // 验证码错误
            return resp(Consts.Code.VERIFY_CODE_INVALID, "验证码错误");
        }
        int res = adminService.updatePwd(phone, pwd);
        return res > 0 ? success() : fail();
    }

    /**
     * 我的页面
     * 
     * @return
     * @throws Exception
     */
    @RequestMapping("me")
    @ResponseBody
    public Resp me(@RequestParam Long userId) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        // 已绑定门店
        List<RespShop> shops = shopService.getValidAuserShopsByAuserId(userId);
        TakeOutShopInfo info = null;
        for (RespShop s : shops) {
            info = shopService.getShopInfo(s.getShopId(), s.getShop_type());
            if (info != null) {
                break;
            }
        }
        result.put("shops", shops);
        if (info == null) {
            info = new TakeOutShopInfo();
            info.setAddress("");
            info.setPictureUrl("");
            info.setName("");
        }
        // 店铺信息
        Admin admin = adminService.getAdminById(userId);
        Map<String, Object> infoMap = new HashMap<String, Object>();
        infoMap.put("logo", info.getPictureUrl());
        infoMap.put("name", info.getName());
        infoMap.put("address", info.getAddress());
        if (admin.getInvitCode() != null) {
            infoMap.put("invitCode", admin.getInvitCode().getCode());
            infoMap.put("tips", admin.isTips());
            infoMap.put("expireAt", admin.getExpireAt());
            long day = Consts.DAY_AGE * 1000;
            long time = CommonHelper.getDateFormat("yyyy-MM-dd", new Date()).getTime();
            long expireAt = CommonHelper.getDateFormat("yyyy-MM-dd", admin.getExpireAt()).getTime();
            long expireDay = (expireAt - time) / day;
            if (expireDay < 0) {
                expireDay = 0;
            }
            infoMap.put("expireDay", expireDay);
        }
        result.put("info", infoMap);
        // 已绑定配送
        List<DeliverAccount> delivers = deliverService.getDeliverAccountList(userId);
        result.put("delivers", delivers);
        return success(result);
    }

    /**
     * 刷新token
     * 
     * @param userId
     * @return
     */
    @ResponseBody
    @RequestMapping("/token")
    public Resp flushToken(@RequestParam String username, @RequestParam String pwd) {
        Admin user = adminService.getAdminByUsername(username);
        if (user == null) {
            log.info("[flushToken] token is invalid user username:{}", username);
            return reqError();
        }
        if (!user.getPwd().equals(pwd)) {
            return reqError();
        }
        return success(flushToken(user.getId(), user.getImid()));
    }

    /**
     * 刷新applog
     * 
     * @param userId
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping("/applog")
    public Resp applog(@RequestParam Long userId, MultipartHttpServletRequest request) throws IOException {

        MultipartFile logFile = request.getFile("logFile");
        if (logFile != null) {
            Admin admin = adminService.getAdminById(userId);
            String filePath = "/data/log/%s";
            String fileName = admin.getUsername() + "_" + CommonHelper.getDateStr("yyyy-MM-dd", new Date()) + "_"
                    + logFile.getOriginalFilename();
            filePath = String.format(filePath, fileName);
            File destFile = new File(filePath);
            FileUtils.copyInputStreamToFile(logFile.getInputStream(), destFile);
            return success();
        }
        return fail();

    }

    /**
     * 邀请码绑定
     * 
     */
    @RequestMapping("/boundCode")
    @ResponseBody
    public Resp boundCode(@RequestParam Long userId, @RequestParam String inviteCode) {

        InvitationCode code = adminService.getInvitationCode(inviteCode);
        if (code == null || code.getState() == 1) {
            return new Resp(Consts.Code.DATA_ERROR, "邀请码错误");
        }
        int res = adminService.updateUserCode(userId, inviteCode);
        return res > 0 ? success() : fail();

    }
}
